
from django.db import models
from django.db.models import F

from apps.login.models import UserInfo
from apps.publish.models import PublishModel,PublishImageModel
from django.forms import model_to_dict
from rest_framework import serializers
from rest_framework.response import Response

# 评论表模型类
class CommentRecordModel(models.Model):
    article = models.ForeignKey(PublishModel,verbose_name="文章",on_delete=models.CASCADE)
    content = models.CharField(verbose_name="评论内容",max_length=255)
    user = models.ForeignKey(UserInfo,verbose_name="评论者",on_delete=models.CASCADE)
    createTime = models.DateTimeField(verbose_name="评论时间",auto_now_add=True)

    reply = models.ForeignKey(verbose_name="回复",to="self",null=True,blank=True,on_delete=models.CASCADE,related_name="replys")
    depth = models.PositiveIntegerField(verbose_name="评论层级",default=1)
    root = models.ForeignKey(verbose_name="根评论",to="self",null=True,blank=True,on_delete=models.CASCADE,related_name="roots")

    favor_count = models.PositiveIntegerField(verbose_name="赞数",default=0)

    # 由于 reply 和root 两个字段关联的是同一个对象，那么后期的字段反查询就查不出来了，所以用了related_name区分

    class Meta:
        db_table = "CommentRecord"
        verbose_name = "用户评论表"
        verbose_name_plural = verbose_name



# 构造数据
def init_comment():
    import os
    import sys
    import django
    base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(base_dir)
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zyy_django.settings")
    django.setup()

    first1 = CommentRecordModel.objects.create(
        article_id=36,
        content="1",
        user_id=1,
        depth=1,

    )
    first1_1 = CommentRecordModel.objects.create(
        article_id=36,
        content="1-1",
        user_id=6,
        reply=first1,
        depth=2,
        root=first1,
    )

    first1_1_1 = CommentRecordModel.objects.create(
        article_id=36,
        content="1-1-1",
        user_id=10,
        reply=first1_1,
        depth=3,
        root=first1,
    )

    first1_1_2 = CommentRecordModel.objects.create(
        article_id=36,
        content="1-1-2",
        user_id=14,
        reply=first1_1,
        depth=3,
        root=first1,
    )

    first1_2 = CommentRecordModel.objects.create(
        article_id=36,
        content="1-2",
        user_id=8,
        reply=first1,
        depth=2,
        root=first1,
    )

    first2 = CommentRecordModel.objects.create(
        article_id=36,
        content="2",
        user_id=3,
        depth=1,
    )

    first3 = CommentRecordModel.objects.create(
        article_id=36,
        content="3",
        user_id=4,
        depth=1,
    )



# 文章详情页序列化器
class PublishDetailModelSerializer(serializers.ModelSerializer):
    images = serializers.SerializerMethodField()
    createTime = serializers.DateTimeField(format="%Y-%m-%d %H:%M")
    topic = serializers.SerializerMethodField()
    user = serializers.SerializerMethodField()
    viewr = serializers.SerializerMethodField() #访客记录
    comment = serializers.SerializerMethodField() # 评论

    class Meta:
        model = PublishModel
        exclude = ["cover",]

    def get_images(self,obj):
        images_queryset =PublishImageModel.objects.filter(article=obj)

        return [model_to_dict(i,fields=["id","cos_path"]) for i in images_queryset]

    def get_topic(self,obj):
        return model_to_dict(obj.topic,fields=["id","topic","count"])

    def get_user(self,obj):
        return model_to_dict(obj.user,fields=["id","nickName","avatarUrl"])

    # 访客记录
    def get_viewr(self,obj):
        print(obj.id)
        queryset = CommentRecordModel.objects.filter(article_id=obj.id)
        print(queryset)
        viewr_object_list = queryset.order_by("-id")[0:10]

        context = {
            "count":queryset.count(),
            "result":[model_to_dict(i.user,fields=["nickName","avatarUrl"]) for i in viewr_object_list]
        }


        return context

    # 评论功能
    def get_comment(self,obj):
        # 获取当前文章下的所有的一级评论
        # user__nickName 是通过 CommentRecord 中的user字段查询 UserInfo中的nickName,user__avatarUrl同理

        first_queryset = CommentRecordModel.objects.filter(article=obj,depth=1).order_by("-id").values(
            "id",'content','depth','user__nickName','user__avatarUrl''createTime'
        )

        # 获取所有一级评论的id列表，下面可以根据此列表获取一级评论下的二级评论
        first_id_list = [i['id'] for i in first_queryset]

        from django.db.models import Max
        # 获取所有一级评论下的二级评论 且 是最新【id最大的】的评论
        result = CommentRecordModel.objects.filter(article=obj,depth=2,reply_id__in=first_id_list).values(
            "reply_id").annotate(max_id=Max("id"))

        # [可以手动添加一行数据，2-1 depth=2 article=36 user_id=4 reply_id=6,root_id=6]

        second_id_list = [i["max_id"]for i in result]

        second_queryset = CommentRecordModel.objects.filter(id__in=second_id_list).values(
            "id","content","user__nickName","createTime","reply_id","reply__user__nickName",
        )
        print(second_queryset)


        # 将 一级评论 和 一级评论下的二级评论 进行嵌套
        import collections
        first_dict = collections.OrderedDict() # 构造一个新的有序字典
        for i in first_queryset:
            i["createTime"] = i["createTime"].strftime("%Y-%m-%d")
            first_dict[i["id"]] = i

        for node in second_queryset:
            first_dict[node["reply_id"]["child"]] = [node,]

        return first_dict.values()


# 评论序列化器
class CommentModelSerializer(serializers.ModelSerializer):
    # user = serializers.SerializerMethodField()
    user__nickName = serializers.CharField(source="user.nickName")
    user__avatar = serializers.CharField(source="user.avatar")
    createTime = serializers.DateTimeField(format="%Y-%m-%d %H:%M")
    # reply_user = serializers.SerializerMethodField()
    reply_id = serializers.CharField(source="reply.id")
    reply__user__nickName = serializers.CharField(source="reply.user.nickName")

    class Meta:
        model = CommentRecordModel
        # fields = "__all__"
        exclude = ["article","user","reply","root"]

    # def get_user(self,obj):
    #     return model_to_dict(obj.user,fields=["id","nickName","avatarUrl"])

    # def get_reply_user(self, obj):
    #     return model_to_dict(obj.reply.user, fields=["id", "nickName",])


# 回复/发布评论序列化器
class CreateCommentModelSerializer(serializers.ModelSerializer):
    # read_only 提交数据不进行验证，但返回数据可以反序列化
    user__nickName = serializers.CharField(source="user.nickName",read_only=True)
    user__avatar = serializers.CharField(source="user.avatarUrl",read_only=True)
    createTime = serializers.DateTimeField(format="%Y-%m-%d %H:%M",read_only=True)
    reply_id = serializers.CharField(source="reply.id",read_only=True)
    reply__user__nickName = serializers.CharField(source="reply.user.nickName",read_only=True)
    class Meta:
        model = CommentRecordModel
        # fields = "__all__"
        exclude = ['user','favor_count']



# 评论视图
from rest_framework.generics import ListAPIView
from rest_framework.views import APIView
from rest_framework import status
class CommentView(APIView):
    def get(self,request):
        # 获取跟评论id
        root_id = request.query_params.get("root")

        # 获取这个根评论的所有子孙评论
        node_queryset = CommentRecordModel.objects.filter(root_id=root_id).order_by("id")

        # 序列化
        ser = CommentModelSerializer(instance=node_queryset,many=True)

        return Response(ser.data,status=status.HTTP_200_OK)

    def post(self,request):
        print(request.data)
        # 进行数据校验
        ser = CreateCommentModelSerializer(data=request.data)
        # 验证通过，保存到数据库 ser.data 获取序列化的数据
        if ser.is_valid():
            ser.save(user_id=1)

            publish_id = ser.data.get("article")
            PublishModel.objects.filter(id=publish_id).update(comment_count=F("comment_count")+1)

            return Response(ser.data,status=status.HTTP_201_CREATED)
        return Response(ser.errors,status=status.HTTP_400_BAD_REQUEST)

        # 将保存到数据库的数据返回给小程序页面



# 评论路由
from django.urls import path
urlpatterns = [
    path("comment/",CommentView.as_view()), #文章详情页
]




